//---------------------------------------------------------------------------
/**
 * \class CFile
 * \brief This is a tool for file & directory
 * \version 0.1
 *
 * \author Woo-Hyun Kim (woorung@nhncorp.com, woorung@gmail.com)
 * \author http://blog.naver.com/wisereign .
 *
 * \date 2007/04/17
 */
//---------------------------------------------------------------------------
#include "CFile.h"
//---------------------------------------------------------------------------
CFile::CFile()
{
}
//---------------------------------------------------------------------------
CFile::~CFile()
{
}
//---------------------------------------------------------------------------
const char *CFile::recognize(const char *buf)
{
	magic_t myt = magic_open(MAGIC_CONTINUE|MAGIC_ERROR|MAGIC_MIME);
	magic_load(myt,NULL);
	magic_number = magic_buffer(myt, buf, strlen(buf));
	magic_close(myt);

	return magic_number.c_str();
}
//---------------------------------------------------------------------------
const char *CFile::magic(const char *file)
{
	magic_t myt = magic_open(MAGIC_CONTINUE|MAGIC_ERROR|MAGIC_MIME);
	magic_load(myt,NULL);
	magic_number = magic_file(myt, file);
	magic_close(myt);

	return magic_number.c_str();
}
//---------------------------------------------------------------------------
const char *CFile::mime_type(const char *file)
{
	int n = strlen(file);
	if(n>4&&(!strcmp(file+n-4,".xml")||!strcmp(file+n-4,".xsd")||!strcmp(file+n-5,".wsdl"))) return "text/xml";
	if(n>4&&!strcmp(file+n-4,".jpg")) return "image/jpg";
	return "*/*";
}
//---------------------------------------------------------------------------
int CFile::file_type(const char *file)
{
	struct stat statbuf;
	struct dirent *dirp;
	DIR *dp;
	int ret;
	char *ptr;

	if(lstat((file),&statbuf)<0) { // stat error
		return -1;
	}

	if(S_ISDIR(statbuf.st_mode)==0) { // in case of file(regular,block,char,fifo,smbolic and sockets)
		switch(statbuf.st_mode&S_IFMT) {
			case S_IFREG : return 1;
			case S_IFBLK : return 2; 
			case S_IFCHR : return 3; 
			case S_IFIFO : return 4; 
			case S_IFLNK : return 5; 
			case S_IFSOCK : return 6;
			case S_IFDIR : return 7; 
		}
	}
	else { // in case of directory
		return 0;
	}
}
//---------------------------------------------------------------------------
bool CFile::executable(const char *file)
{
	magic_t myt = magic_open(MAGIC_CONTINUE|MAGIC_ERROR|MAGIC_MIME);
	magic_load(myt,NULL);
	string tmp_magic_number = magic_file(myt, file);
	magic_close(myt);

	string mime = tmp_magic_number.substr(0, tmp_magic_number.find_first_of("/"));

	if(mime=="application") return true;
	else return false;
}
//---------------------------------------------------------------------------
int CFile::change_mode(const char *file, int mode)
{
	umask(000);
	
	int fd = open(file, O_RDWR);
	if(fchmod(fd, mode)<0) {
		close(fd);

		return -1;
	}

	close(fd);

	return 1;
}
//---------------------------------------------------------------------------
int CFile::separate_path_and_file(string &full_path, string &path, string &file)
{
	// make the end of path be "/" unconditionally
	string::size_type pos = full_path.find_last_of("/"); // only path

	if(pos!=string::npos) {
		path = full_path.substr(0, pos+1);
		file = full_path.substr(pos+1);
	}
	else {
		path = ".";
		file = full_path;
	}

	normalize_file_path(path);
}
//---------------------------------------------------------------------------
string &CFile::normalize_file_path(string &file_path)
{
	// make the end of path be "/" unconditionally
	string::size_type pos = file_path.find_last_of("/"); // only path
	if(pos!=string::npos) {
		if(pos!=file_path.length()-1) file_path += "/";
	}
	else file_path += "/";

	return file_path;
}
//---------------------------------------------------------------------------
bool CFile::exist_dir(const char *dir_path)
{
	DIR *dp;

	if((dp=opendir(dir_path))==NULL) return false;
	else {
		closedir(dp);
		return true;
	}
}
//---------------------------------------------------------------------------
int CFile::make_dir(const char *dir_path)
{
	DIR *dp;

	if((dp=opendir(dir_path))==NULL) {
		mkdir(dir_path, 07777);
	}

	if(dp!=NULL) {
		closedir(dp);
		return 1;
	}

	return -1;
}
//---------------------------------------------------------------------------
int CFile::remove_dir(const char *dir_path)
{
	DIR *dp;
	struct dirent *ep;

	if((dp = opendir(dir_path))==NULL) {
		while(ep=readdir(dp)) {
			remove(ep->d_name);
		}
	}

	if(dp!=NULL) {
		closedir(dp);

		return 1;
	}

	return -1;
}
//---------------------------------------------------------------------------
int CFile::copy(const char *src, const char *dst)
{
	int status = 1;

	ifstream src_file(src, ios::in|ios::binary);
	ofstream dst_file(dst, ios::out|ios::binary);

	if(src_file.is_open()&&dst_file.is_open()) dst_file << src_file.rdbuf();

	if(src_file.fail()) status = -1;
	if(dst_file.fail()) status = -2;

	src_file.close();
	dst_file.close();

	return status;
}
//---------------------------------------------------------------------------
